/* 
 * Copyright 2008 Rodrigo Reyes <reyes.rr at gmail dot com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License. You may
 * obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * permissions and limitations under the License.
**/
package net.kornr.abstractcanvas.awt;

import java.awt.Font;
import java.awt.FontMetrics;
import java.util.LinkedList;

import net.kornr.abstractcanvas.awt.command.ContextRestore;
import net.kornr.abstractcanvas.awt.command.ContextSave;
import net.kornr.abstractcanvas.awt.command.DrawAnnotation;
import net.kornr.abstractcanvas.awt.command.FillColor;
import net.kornr.abstractcanvas.awt.command.GlobalAlpha;
import net.kornr.abstractcanvas.awt.command.LineWidth;
import net.kornr.abstractcanvas.awt.command.PathFill;
import net.kornr.abstractcanvas.awt.command.PathStroke;
import net.kornr.abstractcanvas.awt.command.RectFill;
import net.kornr.abstractcanvas.awt.command.RectStroke;
import net.kornr.abstractcanvas.awt.command.Rotate;
import net.kornr.abstractcanvas.awt.command.Scale;
import net.kornr.abstractcanvas.awt.command.SetPixelHeight;
import net.kornr.abstractcanvas.awt.command.SetPixelWidth;
import net.kornr.abstractcanvas.awt.command.StrokeColor;
import net.kornr.abstractcanvas.awt.command.Translate;

import com.google.gwt.dom.client.ImageElement;
import com.google.gwt.widgetideas.graphics.client.CanvasGradient;
import com.google.gwt.widgetideas.graphics.client.Color;

import net.kornr.abstractcanvas.client.CanvasPainter;
import net.kornr.abstractcanvas.client.CanvasTextSupport;
import net.kornr.abstractcanvas.client.ICanvasExt;
import net.kornr.abstractcanvas.client.Rectangle;
import net.kornr.abstractcanvas.client.TextMetrics;
/**
 * The main AWT implementation of the ICanvasExt interface. This is the object
 * to use if you want to build graphics server-side (or desktop-side, btw).
 * 
 * @author Rodrigo Reyes
 *
 */
@SuppressWarnings("serial")
public class Canvas extends CanvasStack implements ICanvasExt 
{
	private CanvasPath m_cpath = new CanvasPath();
	private String m_fontname = "Serif";
	private int m_fontsize = 12;
	private Font m_font = null;
	private int m_align = CanvasTextSupport.ALIGN_START;
	private LinkedList<CanvasPainter> m_controllers = new LinkedList<CanvasPainter>();
	
	/* Path-Related methods
	 */	
	public void arc(double x, double y, double radius, double startAngle, double endAngle, boolean antiClockwise) 
	{
		m_cpath.arc(x, y, radius, startAngle, endAngle, antiClockwise);
	}
	public void beginPath() 
	{
		m_cpath = new CanvasPath();
		m_cpath.beginPath();
	}
	public void closePath() {
		m_cpath.closePath();
	}
	public void cubicCurveTo(double cp1x, double cp1y, double cp2x,
			double cp2y, double x, double y) {
		m_cpath.cubicCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
	}
	public void fill() 
	{
		PathFill c = new PathFill(m_cpath);
		super.addCommand(c);
	}
	
	public void lineTo(double x, double y) 
	{
		m_cpath.lineTo(x, y);
	}

	public void moveTo(double x, double y) 
	{
		m_cpath.moveTo(x, y);
	}
	
	public void quadraticCurveTo(double cpx, double cpy, double x, double y) 
	{
		m_cpath.quadraticCurveTo(cpx, cpy, x, y);
	}
	
	public void rect(double startX, double startY, double width, double height) 
	{
		m_cpath.rect(startX, startY, width, height);
	}
	
	public void stroke() 
	{
		PathStroke c = new PathStroke(m_cpath);
		super.addCommand(c);
	}

	public void clear() 
	{
		super.clear();
	}

	public CanvasGradient createLinearGradient(double x0, double y0, double x1, double y1) 
	{
		return null;
	}

	public CanvasGradient createRadialGradient(double x0, double y0, double r0,	double x1, double y1, double r1) {
		// TODO Auto-generated method stub
		return null;
	}

	public void drawImage(ImageElement img, double offsetX, double offsetY,
			double width, double height) {
		// TODO Auto-generated method stub
	}

	public void drawImage(ImageElement img, double offsetX, double offsetY) {
		// TODO Auto-generated method stub
	}

	public void fillRect(double startX, double startY, double width, double height) 
	{
		RectFill c = new RectFill(startX, startY, width, height);
		super.addCommand(c);
	}

	public int getCoordHeight() {
		// TODO Auto-generated method stub
		return this.getSize().height;
	}

	public int getCoordWidth() {
		// TODO Auto-generated method stub
		return this.getSize().width;
	}

	public double getGlobalAlpha() {
		// TODO Auto-generated method stub
		return 0;
	}


	public String getGlobalCompositeOperation() {
		// TODO Auto-generated method stub
		return "";
	}


	public String getLineCap() {
		// TODO Auto-generated method stub
		return "";
	}


	public String getLineJoin() {
		// TODO Auto-generated method stub
		return "";
	}


	public double getLineWidth() {
		return 0;
	}


	public double getMiterLimit() {
		// TODO Auto-generated method stub
		return 0;
	}

	public void resize(int width, int height) {
		super.resize(width, height);
	}

	public void restoreContext() 
	{
		super.addCommand(new ContextRestore());
	}

	public void rotate(double angle) 
	{
		Rotate c = new Rotate(angle);
		super.addCommand(c);
	}


	public void saveContext() 
	{
		super.addCommand(new ContextSave());
	}

	public void scale(double x, double y) 
	{
		Scale c = new Scale(x,y);
		super.addCommand(c);
	}

	public void setBackgroundColor(Color color) {
	}


	public void setCoordHeight(int height) {
	}


	public void setCoordSize(int width, int height) {
	}


	public void setCoordWidth(int width) {
	}


	public void setFillStyle(CanvasGradient grad) {
	}

	public void setFillStyle(Color color) 
	{
		FillColor c = new FillColor(color.toString());
		super.addCommand(c);
	}

	public void setGlobalAlpha(double alpha) 
	{
		GlobalAlpha c = new GlobalAlpha(alpha);
		super.addCommand(c);
	}

	public void setGlobalCompositeOperation(String globalCompositeOperation) 
	{
		// TODO: implement
	}


	public void setLineCap(String lineCap) 
	{
		// TODO: implement
	}


	public void setLineJoin(String lineJoin) 
	{
		// TODO: implement
	}


	public void setLineWidth(double width) 
	{
		LineWidth c = new LineWidth(width);
		super.addCommand(c);
	}


	public void setMiterLimit(double miterLimit) 
	{
		// TODO: implement
	}


	public void setPixelHeight(int height) 
	{
		SetPixelHeight c = new SetPixelHeight((double)height);
		this.addCommand(c);
	}

	public void setPixelWidth(int width) 
	{
		SetPixelWidth c = new SetPixelWidth((double)width);
		this.addCommand(c);
	}

	public void setStrokeStyle(CanvasGradient grad) {
	}

	public void setStrokeStyle(Color color) 
	{
		StrokeColor c = new StrokeColor(color.toString());
		super.addCommand(c);
	}

	public void strokeRect(double startX, double startY, double width,
			double height) {
		RectStroke c = new RectStroke(startX, startY, width, height);
		super.addCommand(c);
	}


	public void transform(double m11, double m12, double m21, double m22, double dx, double dy) 
	{
		// TODO: implement
	}


	public void translate(double x, double y) 
	{
		Translate c = new Translate(x,y);
		super.addCommand(c);
	}

	public void strokeText(String text, int x, int y) 
	{
		if (m_font == null)
			updateFont();
		DrawAnnotation c = new DrawAnnotation(text, x, y, m_font, m_align);
		super.addCommand(c);
	}

	public void setFontName(String fontname)
	{
		m_fontname = fontname;
		updateFont();
	}
	
	public void setFontSize(int pixelfontsize)
	{
		m_fontsize = pixelfontsize;
		updateFont();
	}

	private void updateFont()
	{
		int fontsize = m_fontsize;
		if (fontsize < 5)
			fontsize = 5;
		m_font = new Font(m_fontname, Font.PLAIN, fontsize);
	}

	public void setAlign(int align) 
	{
		m_align = align;
	}

	public TextMetrics measureText(String text) 
	{
		// TODO Auto-generated method stub
		if (m_font == null)
			updateFont();
		
		FontMetrics fm = this.getFontMetrics(m_font);
		int width = fm.stringWidth(text);
		int height = fm.getHeight();
		return new TextMetrics((double)width, (double)height);
	}
	
	public void addCanvasPainter(CanvasPainter controller) 
	{
		m_controllers.add(controller);
		controller.drawCanvas(this);
	}

	public void removeCanvasPainter(CanvasPainter controller) 
	{
		m_controllers.remove(controller);
	}


}
